package com.tevintao.marketingsystem.xposted;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;

import com.tevintao.marketingsystem.log.LogManager;

import java.util.List;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

/**
 * Created by tevintao on 2016/9/5.
 */
public class HookPackageManager {
    private static HookPackageManager ourInstance = new HookPackageManager();

    public static HookPackageManager getInstance() {
        return ourInstance;
    }

    private HookPackageManager() {
    }


    public void hookPackageManager(XC_LoadPackage.LoadPackageParam loadPackageParam) {


        try {
            Class c1 = loadPackageParam.classLoader.loadClass("android.app.ApplicationPackageManager");
//            Class c2 = loadPackageParam.classLoader.loadClass("com.android.server.pm.PackageManagerService");
//            Class c3 = Class.forName("android.app.ApplicationPackageManager");
//            Class c4 = Class.forName("com.android.server.pm.PackageManagerService");
            if (null != c1)
                LogManager.getInstance().logInfo("hookPackageManager c1 = " + c1.toString() + "c1.hashCode() = " + c1.hashCode());

//            if (null != c2)
//                LogManager.getInstance().logInfo("hookPackageManager c2 = " + c2.toString() + "c2.hashCode() = " + c2.hashCode());
//
//            if (null != c3)
//                LogManager.getInstance().logInfo("hookPackageManager c3 = " + c3.toString() + "c3.hashCode() = " + c3.hashCode());
//
//            if (null != c4)
//                LogManager.getInstance().logInfo("hookPackageManager c4 = " + c4.toString() + "c4.hashCode() = " + c4.hashCode());


            HookDeviceModule.hookAllMethodByName(c1, "getInstalledPackages", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    LogManager.getInstance().logInfo("hookPackageManager getInstalledPackages c1");
                    LogManager.getInstance().logInfo("c1 getResult = " + param.getResult().toString());
                    LogManager.getInstance().logInfo("param.getResult() class = " + param.getResult().getClass());
                    if (param.getResult() instanceof List) {
                        List list = (List) param.getResult();
                        LogManager.getInstance().logInfo("list size = " + list.size());
                        Object selfInfoObj = null;
                        Object xposedObj = null;
                        for (Object o : list) {
//                            LogManager.getInstance().logInfo("c1 o = " + o.toString());
                            if (o instanceof PackageInfo) {
                                PackageInfo info = (PackageInfo) o;
                                String pName = info.packageName;
                                if (HookDeviceModule.SELF_PACKAGE_NAME.equals(pName)) {
                                    selfInfoObj = o;
                                }
                                if (HookDeviceModule.XPOSED_PACKAGE_NAME.equals(pName)) {
                                    xposedObj = o;
                                }
                            }
                        }
                        if (null != selfInfoObj)
                            list.remove(selfInfoObj);
                        if (null != xposedObj)
                            list.remove(xposedObj);
                        param.setResult(list);
                    }

                }
            });
            HookDeviceModule.hookAllMethodByName(c1, "getInstalledApplications", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    LogManager.getInstance().logInfo("hookPackageManager getInstalledApplications c1");
                    LogManager.getInstance().logInfo("getInstalledApplications getResult = " + param.getResult().toString());
                    LogManager.getInstance().logInfo("getInstalledApplications param.getResult() class = " + param.getResult().getClass());
                    if (param.getResult() instanceof List) {
                        List list = (List) param.getResult();
                        LogManager.getInstance().logInfo("getInstalledApplications list size = " + list.size());
                        Object selfInfoObj = null;
                        Object xposedObj = null;
                        for (Object o : list) {
//                            LogManager.getInstance().logInfo("c1 o = " + o.toString());
                            if (o instanceof ApplicationInfo) {
                                ApplicationInfo info = (ApplicationInfo) o;
                                String pName = info.packageName;
                                if (HookDeviceModule.SELF_PACKAGE_NAME.equals(pName)) {
                                    selfInfoObj = o;
                                }
                                if (HookDeviceModule.XPOSED_PACKAGE_NAME.equals(pName)) {
                                    xposedObj = o;
                                }
                            }
                        }
                        if (null != selfInfoObj)
                            list.remove(selfInfoObj);
                        if (null != xposedObj)
                            list.remove(xposedObj);
                        param.setResult(list);
                    }

                }
            });

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            LogManager.getInstance().logInfo("hookPackageManager ClassNotFoundException");
        }
    }

}
